package com.bolt.report.engine.model;

import com.bolt.common.collection.IteratorUtil;
import com.bolt.common.reflect.ObjectUtil;
import com.bolt.common.utils.ArrayUtil;
import com.bolt.common.utils.StrUtil;
import com.bolt.report.engine.BindData;
import com.bolt.report.engine.ObjectFactory;
import com.bolt.report.engine.calculator.CalculatorFactory;
import com.bolt.report.engine.fill.FillContext;
import com.bolt.report.engine.fill.FillReturnValue;
import com.bolt.report.exception.ReportException;
import org.springframework.expression.spel.standard.SpelExpressionParser;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class Expression implements Serializable {

    private String expr;

    private List<CalculatorExpression> calculatorExpr;

    private BindData bindData;

    private boolean isExecute = true;

    private static Pattern DYNAMIC_PATTERN = Pattern.compile(".*\\$\\{(.*?)\\}.*");
    private static Pattern DYNAMIC_LIMIT_COUNT_PATTERN = Pattern.compile("\\$\\{(.*?)\\}");
    private static Pattern OPERATOR_PATTERN = Pattern.compile(".*[\\+|\\-|\\*|/]+.*");
    private static Pattern CALCULATOR_PATTERN = Pattern.compile("(?:(\\w+)\\s*\\()");

    private static String DEFAULT_DATA_EXPR = "expr_value";

    public Expression(String expr) {
        this(expr, null);
    }

    public Expression(String expr, BindData bindData) {
        this.calculatorExpr = new ArrayList<>();
        this.bindData = bindData;
        parse(expr);
    }

    public BindData getBindData() {
        return bindData;
    }

    public boolean containsCalculator() {
        return IteratorUtil.isNotEmpty(this.calculatorExpr);
    }

    public Object execute(FillContext fillContext, Cell cell) {
        if (containsCalculator()) {

            Map<String, Object> data = new HashMap<>();
            for (CalculatorExpression calculatorExpr : this.calculatorExpr) {
                Object value = CalculatorFactory.evaluate(fillContext, bindData, calculatorExpr, cell);
                data.put(calculatorExpr.getExpr(), value);
            }
            return ObjectFactory.getValueByExpression(this.expr, data);
        } else {
             if( ObjectUtil.isNull(bindData.getData()) && ObjectUtil.isNotNull(this.bindData.getRange())) {
                FillReturnValue returnValue = fillContext.getReturnValue(bindData.getKey());
                return ObjectFactory.getValueByExpression(this.expr, this.bindData.getWrapData(returnValue));
            } else {
                return ObjectFactory.getValueByExpression(this.expr, this.bindData.getWrapData());
            }
        }
    }


    public String getExpr() {
        return expr;
    }

    public void setExpr(String expr) {
        this.expr = expr;
    }

    public String toString() {
        String string = "表达式:{} ";
        String calculator = "函数 {} ,表达式 {} ,参数 {}";
        StringBuffer buffer = new StringBuffer();
        buffer.append(StrUtil.format(string, this.expr));
        for (CalculatorExpression calculatorExpr : this.calculatorExpr) {
            buffer.append(StrUtil.C_LF);
            buffer.append(StrUtil.format(calculator, calculatorExpr.getCalculatorName(), calculatorExpr.getExpr(), calculatorExpr.args));
        }
        return buffer.toString();
    }

    public void parse(String expr) {

        if (StrUtil.isNotBlank(expr) && isDynamicExpr(expr) && ObjectUtil.isNotNull(this.bindData)) {
            Matcher exprMatcher = DYNAMIC_LIMIT_COUNT_PATTERN.matcher(expr);
//            if(isOperatorExpr(expr)){
//                this.expr = expr.replaceAll(".*\\)", "{");
//            }else{
//
//            }
            this.expr = "{}";
            List<String> tempExpression = new ArrayList<>();
            while (exprMatcher.find()) {
                String dynamicExpr = exprMatcher.group(1);
                if (containsCalculator(dynamicExpr)) {
                    Matcher matcher = CALCULATOR_PATTERN.matcher(dynamicExpr);
                    CalculatorExpression calculator = new CalculatorExpression();
                    List<String> names = new ArrayList<>();
                    while (matcher.find()) {
                        String functionName = matcher.group(1).toLowerCase();
                        names.add(functionName);
                    }
                    calculator.setCalculatorName(ArrayUtil.toArray(names, String.class));
                    int startIndex = StrUtil.matchLastIndex(dynamicExpr, "[(]");
                    int endIndex = StrUtil.matchIndex(dynamicExpr, "[)]");
                    if (startIndex == -1 || endIndex == -1) {
                        throw new ReportException("expression calculator function error ");
                    }
                    String temp = StrUtil.sub(dynamicExpr, startIndex + 1, endIndex);

                    if (StrUtil.containsIgnoreCase(temp, StrUtil.COMMA)) {
                        String strArg = StrUtil.subAfter(temp, StrUtil.COMMA, false);
                        String tempExpr = StrUtil.subBetween(temp, StrUtil.DOT, StrUtil.COMMA);
                        calculator.setExpr(tempExpr);
                        tempExpression.add(tempExpr);
                        String[] tempArgs = StrUtil.split(strArg, StrUtil.COMMA);
                        calculator.setArgs(tempArgs);
                    } else if (StrUtil.containsIgnoreCase(temp, StrUtil.DOT)) {
                        String tempExpr = StrUtil.subAfter(temp, StrUtil.DOT, false);
                        calculator.setExpr(tempExpr);
                        tempExpression.add(tempExpr);
                    } else {
                        calculator.setExpr(DEFAULT_DATA_EXPR);
                    }
                    calculatorExpr.add(calculator);
                } else {
                    String tempExpr = StrUtil.subAfter(dynamicExpr, StrUtil.DOT, false);
                    if (StrUtil.isNotBlank(tempExpr)) {
                        tempExpression.add(tempExpr);
                    }
                }
            }
            if (IteratorUtil.isEmpty(tempExpression)) {
                tempExpression.add(DEFAULT_DATA_EXPR);
            }
            this.expr = StrUtil.format( this.expr, ArrayUtil.toArray(tempExpression, String.class));
        } else {
            this.isExecute = false;
            this.expr = expr;
        }
    }

    public static boolean containsCalculator(String expr) {
        return expr != null && expr.contains("(") && expr.contains(")");
    }

    public static boolean isDynamicExpr(String expr) {
        return DYNAMIC_PATTERN.matcher(expr).matches();
    }


    public static boolean isOperatorExpr(String expr) {
        return OPERATOR_PATTERN.matcher(expr).matches() || containsCalculator(expr);
    }

    public boolean isExecute() {
        return isExecute;
    }

    public class CalculatorExpression {
        private String expr;

        private String[] calculatorName;

        private String[] args;

        public CalculatorExpression() {
        }

        public CalculatorExpression(String expr, String[] calculatorName, String[] args) {
            this.expr = expr;
            this.calculatorName = calculatorName;
            this.args = args;
        }

        public String getExpr() {
            return expr;
        }

        public void setExpr(String expr) {
            this.expr = expr;
        }

        public String[] getCalculatorName() {
            return calculatorName;
        }

        public void setCalculatorName(String[] calculatorName) {
            this.calculatorName = calculatorName;
        }

        public String[] getArgs() {
            return args;
        }

        public void setArgs(String[] args) {
            this.args = args;
        }
    }


    public static void main(String[] args) {
//        String amp = "${checkup.details.C0003.inputValue}+\" cm\"".replaceAll(".+(?=\\+)", "{}");
//        System.out.println(amp);

         String regex = "[+\\-*/]";

        String input = "${checkup.details.C0003.inputValue}+\" cm\"";

        // 使用正则表达式将字符串分隔成多个部分
        String[] parts = input.split("[+\\-*/]");

        // 打印分隔后的部分
        for (String part : parts) {
            System.out.println(part.trim()); // 使用 trim() 方法去除空格
        }

        SpelExpressionParser parser = new SpelExpressionParser();

        org.springframework.expression.Expression  exp1 = parser.parseExpression("'Hello World'.length()");
        System.out.println(exp1.getValue());

    }

}